package com.exam.scjp5.objectives.section_6;

import java.util.ArrayList;
import java.util.List;

public class ExampleGeneric
{
    public static void main(String args[])
    {
        // OK.. because Number is parent of Integer
        List<? super Integer> list1 = new ArrayList<Number>();
        list1.add(1);
        
        // OK.. because Integer extends Number
        List<? extends Number> list2 = new ArrayList<Integer>();
        list1.add(1); // Here OK..
        
        // ERROR.. because Integer is subclass of Number. Not parent of Number.
        List<? super Number> list3 = new ArrayList<Integer>();
        
        List<T extends Number> list = new List<Interger>(); // Error.. cant use like this
    }
    
    /**
     * Here, elements in the list will be the same type.
     */
    public <T extends Number> List<T> method1(List<T> number, T e)
    {
        number.add(e);
        return number;
    }
    
    /**
     * Here, elements in the list can be any subclass of Number and
     * will not be the same type because of '?'.
     * So, compiler will not allow to add different.
     */
    public List<? extends Number> method2(List<? extends Number> number)
    {
        number.add(new Integer(10)); // Someone may add Integer
        number.add(new Double(10)); // Someone may add Double. So, this is ambiguous case.
        return number;
    }
    
    /**
     * Here, elements in the list may be any superclass of TestChild.
     * And compiler will allow only the TestChild class to be added into list.
     */
    public List<? super TestChild> method2(List<? super TestChild> number)
    {
        number.add(new TestChild());
        // Let's say, you declared List<TestParent>. It is ok because it will accept
        // any superclass of TestChild because of <? super TestChild>. In this case,
        // you may want to add TestGrandParent to list. Compiler will accept it because
        // TestGrandParent is also superclass of TestChild. But at run time, it will be problem,
        // so compiler protect such kind of action. And show error when you try to add
        // superclass of TestChild.
        number.add(new TestParent());    
        number.add(new TestGrandParent());    
        return number;
    }
}

class TestGrandParent {}
class TestParent extends TestGrandParent {}
class TestChild {}
